
bt.module({builder: function(bt) {

    var parseGPX = function(gpxDoc) {
        if( !gpxDoc ) {
            alert("Could not load GPX document " + URL);
        } else if( !gpxDoc.documentElement ) {
            alert("Document " + URL + "\nwas not recognized by the XML loader");
        } else if( gpxDoc.documentElement.childNodes.length < 3 ) {
            alert("The XML loader could not parse document " + URL);
        } else {
            //
            //	Parse document <bounds>.  Open map.  Guess at zoom level.
            //
            var minlat 		= 0;
            var minlon 		= 0;
            var maxlat 		= 0;
            var maxlon 		= 0;
            var bounds = gpxDoc.documentElement.getElementsByTagName("bounds");
            if( bounds && bounds.length ) {
                minlat = parseFloat(bounds[0].getAttribute("minlat"));
                minlon = parseFloat(bounds[0].getAttribute("minlon"));
                maxlat = parseFloat(bounds[0].getAttribute("maxlat"));
                maxlon = parseFloat(bounds[0].getAttribute("maxlon"));
            }
            var zoomlat		= minlat+(maxlat-minlat)/2;
            var zoomlon		= minlon+(maxlon-minlon)/2;
            map.centerAndZoom(new GPoint(zoomlon,zoomlat),zoomlevel);
            bounds = [];

            //	Parse waypoints in <wpt></wpt> tags
            //
            var wpt;
            wpt = gpxDoc.documentElement.getElementsByTagName("wpt")
                if( wpt ) {
                    for (var i = 0; i < wpt.length; i++) {

                        var point = new GPoint(parseFloat(wpt[i].getAttribute("lon")),
                                parseFloat(wpt[i].getAttribute("lat")));

                        // Extract <name></name> tag
                        var tname  = "";
                        var tlabel = "";
                        var element = wpt[i].getElementsByTagName("name");
                        if( element.length ) {
                            tname   = element[0].firstChild.nodeValue;
                            tlabel += element[0].firstChild.nodeValue;
                        }

                        // Tack on  <cmt></cmt> tag
                        element = wpt[i].getElementsByTagName("cmt");
                        if( element.length ) {
                            if(tlabel) { tlabel += ": "; }
                            tlabel += element[0].firstChild.nodeValue;
                        }

                        // Tack on <desc></desc> tag
                        element = wpt[i].getElementsByTagName("desc");
                        if( element.length ) {
                            if(tlabel) { tlabel += " - "; }
                            tlabel += element[0].firstChild.nodeValue;
                        }

                        // Extract <url></url> tag, build html for popup
                        element = wpt[i].getElementsByTagName("url");
                        if( element.length ) {
                            turl = element[0].firstChild.nodeValue;
                            var thtml 	= "<a href=\"" + turl + "target=\"_blank\">" + tlabel + "</a>";
                        } else {
                            var thtml	= tlabel;
                        }

                        // Determine map symbol based on <type></type> tag
                        var myicon = green_pin;
                        var type = wpt[i].getElementsByTagName("type");
                        if( type.length ) {
                            myicon = chooseIcon( tname, type[0].firstChild.nodeValue );
                        }

                        createMarker(point, thtml, myicon);
                    }
                }
            wpt = [];


            //	Parse routes in <rte></rte>
            //
            var rte;
            rte = gpxDoc.documentElement.getElementsByTagName("rte");
            if (rte) {
                // Process each route
                //
                for (var i = 0; i < rte.length; i++) {
                    var tcolor="#4012FE";
                    var twidth=6;
                    var topacity=.7;

                    // Extract <name></name> tag
                    tname = "";
                    element = rte[i].getElementsByTagName("name");
                    if( element.length ) {
                        if( element[0].firstChild ) {
                            tname = element[0].firstChild.nodeValue;
                        }
                    }

                    // Determine line color based on <cmt></cmt> and <name></name> tags
                    type = rte[i].getElementsByTagName("cmt");
                    if( type.length ) {
                        if( type[0].firstChild ) {
                            var array    = chooseLineStyle( tname, type[0].firstChild.nodeValue );
                            tcolor   = array[0];
                            twidth   = array[1];
                            topacity = array[2];
                        }
                    }

                    // Process each point of each route, string 
                    // them into a single polyline
                    //
                    var points = [];
                    var rtept = rte[i].getElementsByTagName("rtept");
                    for (var k = 0; k < rtept.length; k++) {
                        points.push(new GPoint(
                                    parseFloat(rtept[k].getAttribute("lon")),
                                    parseFloat(rtept[k].getAttribute("lat"))));
                    }
                    map.addOverlay(new GPolyline(points, tcolor, twidth, topacity));
                    points = [];
                }
                rte = []
            }
        }
    };

    var _gpx = function(data) {
        var points = [];
        var bounds = new google.maps.LatLngBounds();
        j$(data).find("trkpt").each(function() {
            var lat = j$(this).attr("lat");
            var lon = j$(this).attr("lon");
            var time = j$(this).find("time").text();
            if(!time) {
                return;
            }
            var p = new google.maps.LatLng(lat, lon);
            p.time = time;
            points.push(p);
            bounds.extend(p);
        });
        return [points, bounds];
    };

    var _kml = function(data) {
        var points = [];
        var bounds = new google.maps.LatLngBounds();
        j$(data).find("coordinates").each(function() {
            var coordinates = j$(this).text().replace(/^[ ]+/, "").replace(/([ ]+)/g, " ");
            var coordinates = coordinates.split(" ");
            for(var i in coordinates) {
                var data = coordinates[i].split(",");
                if(data.length < 2) {
                    continue;
                }
                var p = new google.maps.LatLng(data[1], data[0]);
                points.push(p);
                bounds.extend(p);
            }
        });
        return [points, bounds];
    };

    var parseGPS = function(data) {
        var type;
        var data = j$(data);

        if(j$.browser.msie) {
            type = data.children().get(0).tagName;
        } else {
            type = data.get(2).tagName;
        }

        if(type.toLowerCase() == "gpx") {
            return _gpx(data);
        } else if(type.toLowerCase() == "kml") {
            return _kml(data);
        }
    };

    bt.misc.parseGPX = parseGPX;
    bt.misc.parseGPS = parseGPS;
}});
